package com.schematic.android
{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TouchEvent;
import flash.events.TransformGestureEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.ui.Multitouch;

import mx.controls.Text;

/**
 * Provides an invisible game controller
 */
public class Controller extends Sprite
{
    //--------------------------------------------------------------------------
    //
    //  Class Constants
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  JOYSTICK_COLOR
    //----------------------------------
    /**
     * The default joystick debug color
     */
    public static const JOYSTICK_COLOR:int = 0x00FF00;

    //----------------------------------
    //  BUTTON_COLOR
    //----------------------------------
    /**
     * The default button debug color
     */
    public static const BUTTON_COLOR:int = 0xFF0000;
    
    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Creates a new instance of this class.
     */
    public function Controller(debug:Boolean = false)
    {
        super();
        this.debug = debug;

        joystick = new Sprite();
        addChild(joystick);
        joystick.addEventListener(
            TouchEvent.TOUCH_BEGIN, joystick_touchBeginHandler);
        joystick.addEventListener(
            TouchEvent.TOUCH_MOVE, joystick_touchMoveHandler);
        joystick.addEventListener(
            TouchEvent.TOUCH_END, joystick_touchEndHandler);

        button = new Sprite();
        addChild(button); 
        button.addEventListener(TouchEvent.TOUCH_BEGIN, button_touchBeginHandler);
        button.addEventListener(TouchEvent.TOUCH_END, button_touchEndHandler);

        addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  joystick
    //----------------------------------
    /**
     *  @private
     */
    private var joystick:Sprite;

    //----------------------------------
    //  button
    //----------------------------------
    /**
     *  @private
     */
    private var button:Sprite;

    //----------------------------------
    //  debug
    //----------------------------------
    /**
     *  @private
     */
    private var debug:Boolean;

    //----------------------------------
    //  monitor
    //----------------------------------
    /**
     *  @private
     */
    private var monitor:TextField;

    //----------------------------------
    //  joystickPoint
    //----------------------------------
    /**
     *  @private
     */
    private var joystickPoint:Point;
   
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  up
    //----------------------------------

    /**
     *  @private
     */
    private var _up:Boolean;

    /**
     * true if joystick is pointing up
     */
    public function get up():Boolean
    {
        return _up;
    }

    //----------------------------------
    //  down
    //----------------------------------

    /**
     *  @private
     */
    private var _down:Boolean;

    /**
     * true if joystick is pointing down
     */
    public function get down():Boolean
    {
        return _down;
    }

    //----------------------------------
    //  left
    //----------------------------------

    /**
     *  @private
     */
    private var _left:Boolean;

    /**
     * true if joystick is pointing left
     */
    public function get left():Boolean
    {
        return _left;
    }

    //----------------------------------
    //  right
    //----------------------------------

    /**
     *  @private
     */
    private var _right:Boolean;

    /**
     * true if joystick is pointing right
     */
    public function get right():Boolean
    {
        return _right;
    }

    //----------------------------------
    //  buttonDown
    //----------------------------------

    /**
     *  @private
     */
    private var _buttonDown:Boolean;

    /**
     * true if the button is down
     */
    public function get buttonDown():Boolean
    {
        return _buttonDown;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  drawController
    //----------------------------------
    /**
     * @private
     */
    private function drawController(controller:Sprite, width:Number, height:Number,
                                                        color:int=0x00FF00):void
    {
        var controlAlpha:Number = debug ? 1 : 0;
        controller.graphics.clear();
        controller.graphics.beginFill(color, controlAlpha);
        controller.graphics.drawRect(0, 0, width / 2, height / 2);
        controller.graphics.endFill();
    }

    //----------------------------------
    //  updateControls
    //----------------------------------
    /**
     * Updates the controls layout to match the screen
     */
    public function updateControls():void
    {
        var width:Number = stage.stageWidth;
        var height:Number = stage.stageHeight;
        
        drawController(joystick, width, height, JOYSTICK_COLOR);
        joystick.x = 0;
        joystick.y = height / 2;

        drawController(button, width, height, BUTTON_COLOR);
        button.x = width / 2;
        button.y = height / 2;
    } 

    //----------------------------------
    //  createMonitor
    //----------------------------------
    /**
     * @private
     */
    private function createMonitor():void
    {
        monitor = new TextField();
        monitor.width = stage.stageWidth;
        monitor.height = stage.stageHeight / 2;
        var textFormat:TextFormat = new TextFormat("Arial", "18", 0xFFFFFF);
        textFormat.align = TextFormatAlign.CENTER;
        monitor.defaultTextFormat = textFormat;
        monitor.text = "- DEBUG MODE -\n";
        monitor.appendText("GREEN: Joystic (swipe)\n");
        monitor.appendText("RED:Button (click)\n");
        monitor.appendText("Multitouch.inputMode: " +  Multitouch.inputMode + "\n");
        addChild(monitor);
    } 

    //----------------------------------
    //  updateMonitor
    //----------------------------------
    /**
     * @private
     */
    private function updateMonitor(text:String):void
    {
        monitor.text = text +  "\n" + monitor.text;
    } 

    //--------------------------------------------------------------------------
    //
    //  Event Handlers
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */    
    private function addedToStageHandler(event:Event):void
    {
        updateControls();
        
        if (debug)
            createMonitor();
    }

    //----------------------------------
    //  button_touchTapHandler
    //----------------------------------
    /**
     * @private
     */
    private function button_touchBeginHandler(event:TouchEvent):void
    {
        _buttonDown = true;
        if (debug)
            updateMonitor("buttonDown: " + buttonDown); 
    }   

    //----------------------------------
    //  button_touchEndHandler
    //----------------------------------
    /**
     * @private
     */
    private function button_touchEndHandler(event:TouchEvent):void
    {
        _buttonDown = false;
        if (debug)
            updateMonitor("buttonDown: " + buttonDown); 
    } 
    
    //----------------------------------
    //  joystick_touchBeginHandler
    //----------------------------------
    /**
     * @private
     */
    private function joystick_touchBeginHandler(event:TouchEvent):void
    {
        if (debug)
            updateMonitor("joystick: " + event.type); 
        
        joystickPoint = new Point(event.localX, event.localY);
    }

    //----------------------------------
    //  joystick_touchMoveHandler
    //----------------------------------
    /**
     * @private
     */
    private function joystick_touchMoveHandler(event:TouchEvent):void
    {
        
        var currentPoint:Point = new Point(event.localX, event.localY);
        var minOffset:int = 5;
        
        if (currentPoint.x < (joystickPoint.x - minOffset))
        {
            _left = true;
            _right = false;
        }
        else if (currentPoint.x > (joystickPoint.x + minOffset))
        {
            _left = false;        
            _right = true;        
        }
        
        if (currentPoint.y < (joystickPoint.y - minOffset))
        {
            _up = true;
            _down = false;        
        }
        else if (currentPoint.y > (joystickPoint.y + minOffset))
        {
            _up = false;        
            _down = true;
        }
        
        if (debug)
        {
            updateMonitor("left: " + left);
            updateMonitor("right: " + right);
            updateMonitor("up: " + up);
            updateMonitor("down: " + down);
        }
        
        joystickPoint = currentPoint;
    }

    //----------------------------------
    //  joystick_touchEndHandler
    //----------------------------------
    /**
     * @private
     */
    private function joystick_touchEndHandler(event:TouchEvent):void
    {
        _up = _down = _left = _right = false;
        if (debug)
        {
            updateMonitor("left: " + left);
            updateMonitor("right: " + right);
            updateMonitor("up: " + up);
            updateMonitor("down: " + down);
        }
        joystickPoint = null;
    }
}
}